package com.dxj.aop;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;

/**
 * @author dxj
 * @Description aop记录请求参数,拦截ApiOperation 这个注解的值，从请求中获取信息
 * @date 2024/7/5 15:50
 */
@Aspect
@Component
@Slf4j
public class LoggingAspect {
    @Pointcut("@annotation(io.swagger.annotations.ApiOperation)||@within(io.swagger.annotations.ApiOperation)")
    public void loggerPrint() {
    }
    @AfterReturning(value = "loggerPrint()", returning = "keys")
    public void afterReturning(JoinPoint joinPoint, Object keys) {
        log.info("==> method start");
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            if (request != null) {
                // 获取ApiOperation注解的值
                ApiOperation loggerPrintAnnotation = getAnnotationFromJoinPoint(joinPoint, ApiOperation.class);
                String annotationValue = (loggerPrintAnnotation != null) ? loggerPrintAnnotation.value() : "";
                //注解的值加到方法名称的后面
                String methodName = joinPoint.getSignature().getName()+"-"+annotationValue;
                String methodType = request.getMethod();
                String requestUrl = request.getRequestURL().toString();
                //获取方法的参数信息
                Map<String, String[]> parameterMap=new HashMap<>(16);
                parameterMap = request.getParameterMap();
                for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                    String name = entry.getKey();
                    String[] values = entry.getValue();
                    for (String value : values) {
                        log.info("==>requestParams:{}:{}",name,value);
                    }
                }
                log.info("==>MethodName:{},RequestType:{},RequestURL:{}", methodName, methodType, requestUrl);
            } else {
                log.warn("No HttpServletRequest found in the current context.");
            }
        } catch (IllegalStateException  e) {
            log.error("Failed to access HttpServletRequest in the current context.", e);
        }
    }

    /**
     * 辅助方法：从JoinPoint中获取指定类型的注解
     * @param joinPoint
     * @param annotationClass
     * @param <T>
     * @return
     */
    private <T extends Annotation> T getAnnotationFromJoinPoint(JoinPoint joinPoint, Class<T> annotationClass) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod().getAnnotation(annotationClass);
    }
}
